package com.wmyg.antifake.service.impl;

import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradePrecreateModel;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConstants;
import com.wmyg.antifake.alipay.AlipayConfig;
import com.wmyg.antifake.entity.BkUser;
import com.wmyg.antifake.entity.Order;
import com.wmyg.antifake.entity.Record;
import com.wmyg.antifake.entity.UserAddress;
import com.wmyg.antifake.repository.BkUserRepository;
import com.wmyg.antifake.repository.OrderRepository;
import com.wmyg.antifake.repository.RecordRepository;
import com.wmyg.antifake.repository.UserAddressRepository;
import com.wmyg.antifake.service.OrderService;
import com.wmyg.antifake.utils.TsStringCreator;
import com.wmyg.antifake.wxpay.MiaomarkWxConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 王卓逸
 * @program TODO
 * @description TODO
 * @create 2019-05-26
 */
@Slf4j
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    OrderRepository orderRepository;

    @Autowired
    BkUserRepository bkUserRepository;

    @Autowired
    RecordRepository recordRepository;

    @Autowired
    UserAddressRepository userAddressRepository;

    @Value(value = "${wxpay.usesandbox}")
    Boolean useSandbox;

    @Value(value = "${alipay.usesandbox}")
    Boolean aliuseSandbox;

    @Override
    public Integer createOrder(Order order, Integer recordId, Integer addressId, String username) {
        BkUser user = bkUserRepository.findByUsername(username);
        if (null == user || null == user.getCompany()) {
            return -1;
        } else {
            order.setCompany(user.getCompany());
        }
        Record record = recordRepository.findByRecordId(recordId);
        if (null == record) {
            return -1;
        } else {
            order.setRecord(record);
            order.setPrice(5 * record.getTotalPrice());
        }
        UserAddress address = userAddressRepository.getOne(addressId);
        if (null == address) {
            return -1;
        } else {
            order.setUserAddress(address);
        }
        orderRepository.save(order);
        return order.getOrderId();
    }

    @Override
    public Order getOrder(Integer orderId) {
        return orderRepository.findByOrderId(orderId);
    }

    @Override
    public String wxPayPre(Integer orderId, String clientIp) {
        Order order = orderRepository.findByOrderId(orderId);
        if (StringUtils.isNotBlank(order.getWxpayCodeUrl())) {
            return order.getWxpayCodeUrl();
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmssSSS");
        String outTradeNo = sdf.format(new Date()) + TsStringCreator.parseInt(order.getOrderId(), 17);
        try {
            MiaomarkWxConfig miaomarkWxConfig = new MiaomarkWxConfig();
            WXPay wxpay = new WXPay(miaomarkWxConfig, WXPayConstants.SignType.MD5, useSandbox);
            if (useSandbox) {
                miaomarkWxConfig.retrieveSandboxSignKey(wxpay);
            }
            Map<String, String> data = new HashMap<String, String>();
            data.put("body", "妙码服务生成二维码印刷品");
            data.put("out_trade_no", outTradeNo);
            data.put("device_info", "");
            data.put("fee_type", "CNY");
            if (useSandbox) {
                data.put("total_fee", "301");
            } else {
                data.put("total_fee", order.getPrice().toString());
            }
            data.put("spbill_create_ip", clientIp);
            if (useSandbox) {
                data.put("notify_url", "https://apid.miaomark.cn/notice/wxpay");
            } else {
                data.put("notify_url", "https://api.miaomark.cn/notice/wxpay");
            }
            data.put("trade_type", "NATIVE");  // 此处指定为扫码支付
            data.put("product_id", outTradeNo);
            data.put("attach", "PRINTORDER");
            Map<String, String> resp = wxpay.unifiedOrder(data);
            if (WXPayConstants.SUCCESS.equals(resp.get("return_code")) &&
                    WXPayConstants.SUCCESS.equals(resp.get("result_code"))) {
                String code = resp.get("code_url");
                order.setWxpayCodeUrl(code);
                order.setWxpayId(outTradeNo);
                order.setWxpayPrepayId(resp.get("prepay_id"));
                order.setOrderState((order.getOrderState() | 1) & 3);
                orderRepository.save(order);
                return code;
            } else {
                log.error("The wxpay has a error with {}", resp);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "error";
    }

    @Override
    public String aliPayPre(Integer orderId) {
        Order order = orderRepository.findByOrderId(orderId);
        if (StringUtils.isNotBlank(order.getAlipayCodeUrl())) {
            return order.getAlipayCodeUrl();
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmssSSS");
        String outTradeNo = "P" + sdf.format(new Date()) + TsStringCreator.parseInt(order.getOrderId(), 16);
        try {
            AlipayClient alipayClient = null;
            if (aliuseSandbox) {
                alipayClient = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
            } else {
                alipayClient = new DefaultAlipayClient(AlipayConfig.URL_PROD, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY_PROD, AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY_PROD, AlipayConfig.SIGNTYPE);
            }
            AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
            AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
            model.setOutTradeNo(outTradeNo);
            model.setSubject("妙码服务生成二维码印刷品");
            model.setTotalAmount(order.getPrice() / 100 + "." + order.getPrice() % 100);
            request.setBizModel(model);
            request.setNotifyUrl(AlipayConfig.notify_url);
            AlipayTradePrecreateResponse response = alipayClient.execute(request);
            log.info("recieve ali response {}", response);
            if (response.isSuccess()) {
                String code = response.getQrCode();
                order.setAlipayCodeUrl(code);
                order.setAlipayId(outTradeNo);
                order.setOrderState((order.getOrderState() | 2) & 3);
                orderRepository.save(order);
                return code;
            } else {
                log.error("The alipay has a error with {}", response.getMsg());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "error";
    }

    @Override
    public Page<Order> getOrderPage(String username, Integer index, Date startTime, Date endTime, Integer state) {
        if (null == state) {
            if (null == startTime && null == endTime) {
                return orderRepository.findByCompanyOrderByCreateTimeDesc(bkUserRepository.findByUsername(username).getCompany(), PageRequest.of(index, 10));
            } else if (null == startTime) {
                return orderRepository.findByCompanyAndCreateTimeBeforeOrderByCreateTimeDesc(bkUserRepository.findByUsername(username).getCompany(), endTime, PageRequest.of(index, 10));
            } else if (null == endTime) {
                return orderRepository.findByCompanyAndCreateTimeBetweenOrderByCreateTimeDesc(bkUserRepository.findByUsername(username).getCompany(), startTime, new Date(), PageRequest.of(index, 10));
            } else {
                return orderRepository.findByCompanyAndCreateTimeBetweenOrderByCreateTimeDesc(bkUserRepository.findByUsername(username).getCompany(), startTime, endTime, PageRequest.of(index, 10));
            }
        } else if (state < 4) {
            if (null == startTime && null == endTime) {
                return orderRepository.findByCompanyAndOrderStateLessThanOrderByCreateTimeDesc(bkUserRepository.findByUsername(username).getCompany(), state, PageRequest.of(index, 10));
            } else if (null == startTime) {
                return orderRepository.findByCompanyAndOrderStateLessThanAndCreateTimeBeforeOrderByCreateTimeDesc(bkUserRepository.findByUsername(username).getCompany(), state, endTime, PageRequest.of(index, 10));
            } else if (null == endTime) {
                return orderRepository.findByCompanyAndOrderStateLessThanAndCreateTimeBetweenOrderByCreateTimeDesc(bkUserRepository.findByUsername(username).getCompany(), state, startTime, new Date(), PageRequest.of(index, 10));
            } else {
                return orderRepository.findByCompanyAndOrderStateLessThanAndCreateTimeBetweenOrderByCreateTimeDesc(bkUserRepository.findByUsername(username).getCompany(), state, startTime, endTime, PageRequest.of(index, 10));
            }
        } else {
            if (null == startTime && null == endTime) {
                return orderRepository.findByCompanyAndOrderStateOrderByCreateTimeDesc(bkUserRepository.findByUsername(username).getCompany(), state, PageRequest.of(index, 10));
            } else if (null == startTime) {
                return orderRepository.findByCompanyAndOrderStateAndCreateTimeBeforeOrderByCreateTimeDesc(bkUserRepository.findByUsername(username).getCompany(), state, endTime, PageRequest.of(index, 10));
            } else if (null == endTime) {
                return orderRepository.findByCompanyAndOrderStateAndCreateTimeBetweenOrderByCreateTimeDesc(bkUserRepository.findByUsername(username).getCompany(), state, startTime, new Date(), PageRequest.of(index, 10));
            } else {
                return orderRepository.findByCompanyAndOrderStateAndCreateTimeBetweenOrderByCreateTimeDesc(bkUserRepository.findByUsername(username).getCompany(), state, startTime, endTime, PageRequest.of(index, 10));
            }
        }
    }

    @Override
    public Boolean cancelOrder(Integer orderId) {
        Order order = orderRepository.findByOrderId(orderId);
        order.setOrderState(8);
        order.setRecord(null);
        orderRepository.save(order);
        return true;
    }
}
